package com.gustavo.sistema.dao.jdbc;

import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.gustavo.sistema.dao.ErroDeBancoDeDados;
import com.gustavo.sistema.dao.ProdutoDao;
import com.gustavo.sistema.model.Produto;

public class ProdutoDaoJdbc extends DaoJdbc implements ProdutoDao {
	
	private static final String INSERIR_PRODUTO = "insert into produto (unidade, descricao, data_cadastro, estoque, valor) values (?,?,?,?,?);";
	private static final String ATUALIZA_PRODUTO = "update produto set unidade=?, descricao =?, data_cadastro=?, estoque=?, valor=? where id = ?";
	private static final String EXCLUI_PRODUTO = "delete from produto where id=?";
	private static final String LISTAR_PRODUTO = "select id,unidade, descricao, data_cadastro, estoque, valor from produto ORDER BY descricao";
	private static final String CONSULTA_POR_ID = "select * from produto where id = ?";

	
	public ProdutoDaoJdbc() {
	}

	@Override
	public boolean inserirProduto(Produto produto) throws ErroDeBancoDeDados {
		
		try {
			// abre uma conexao com banco
			abrirConexao();

			// preenche a query para realizar o "insert"
			PreparedStatement preparedStatement = conexao.prepareStatement(INSERIR_PRODUTO);

			int i = 1;
			preparedStatement.setString(i++, produto.getUnidade());
			preparedStatement.setString(i++, produto.getDescricao());
			preparedStatement.setDate(i++, new Date(produto.getDataCadastro().getTime()));
			preparedStatement.setInt(i++, produto.getEstoque());
			preparedStatement.setFloat(i++, produto.getValor());

			// caso a operacao seja realizada, retorna true
			if (preparedStatement.executeUpdate() > 0) {
				return true;
			}
			// caso contrario retorna false
			return false;

		} catch (SQLException e) {
			// caso ocorra qualquer erro ao executar a operacao no banco de dados
			throw new ErroDeBancoDeDados(e);

		} finally {
			// independente de sucesso/erro fecha a conexao com banco de dados
			fecharConexao();
		}
	}				
		
		
	@Override
	public boolean atualizarProduto(Produto produto) throws ErroDeBancoDeDados {
		
		try {
			abrirConexao();

			PreparedStatement preparedStatement = conexao.prepareStatement(ATUALIZA_PRODUTO);

			int i = 1;
			preparedStatement.setString(i++, produto.getUnidade());
			preparedStatement.setString(i++, produto.getDescricao());
			preparedStatement.setDate(i++, new Date(produto.getDataCadastro().getTime()));
			preparedStatement.setInt(i++, produto.getEstoque());
			preparedStatement.setFloat(i++, produto.getValor());
			preparedStatement.setInt(i++, produto.getId());
			
			if (preparedStatement.executeUpdate() > 0) {
				return true;
			}
			return false;
		} catch (SQLException e) {
			e.printStackTrace();
			// caso ocorra qualquer erro ao executar a operacao no banco de dados
			throw new ErroDeBancoDeDados(e);

		} finally {
			// independente de sucesso/erro fecha a conexao com banco de dados
			fecharConexao();
		}
	}	
		
		
	@Override
	public boolean excluirProduto(Integer id) throws ErroDeBancoDeDados {
		
		try {
			abrirConexao();

			PreparedStatement preparedStatement = conexao.prepareStatement(EXCLUI_PRODUTO);

			preparedStatement.setInt(1, id);

			if (preparedStatement.executeUpdate() > 0) {
				return true;
			}
			return false;
		} catch (SQLException e) {
			// caso ocorra qualquer erro ao executar a operacao no banco de
			// dados
			throw new ErroDeBancoDeDados(e);

		} finally {
			// independente de sucesso/erro fecha a conexao com banco de dados
			fecharConexao();
		}
	}		
		
		
		
	@Override
	public List<Produto> listarProdutos() throws ErroDeBancoDeDados {
		
		try {
			abrirConexao();

			PreparedStatement preparedStatement = conexao.prepareStatement(LISTAR_PRODUTO);

			// Executa a consulta SQL neste objeto PreparedStatement e retorna o objeto ResultSet gerado pela consulta.
			ResultSet rs = preparedStatement.executeQuery();

			List<Produto> produtos = new ArrayList<Produto>();

			while (rs.next()) {				

				Produto produto = new Produto();
				produto.setId(rs.getInt("id"));
				produto.setUnidade(rs.getString("unidade"));
				produto.setDescricao(rs.getString("descricao"));
				produto.setDataCadastro(rs.getDate("data_cadastro"));
				produto.setEstoque(rs.getInt("estoque"));
				
				produtos.add(produto);
			}
			return produtos;

		} catch (SQLException e) {
			// caso ocorra qualquer erro ao executar a operacao no banco de dados
			throw new ErroDeBancoDeDados(e);

		} finally {

			// independente de sucesso/erro fecha a conexao com banco de dados
			fecharConexao();
		}

	}

	@Override
	public Produto consultaPorId(Integer id) throws ErroDeBancoDeDados {
		try {
			abrirConexao();

			// Executa a query buscando o objeto com o id passado por paramentro 
			PreparedStatement preparedStatement = conexao.prepareStatement(CONSULTA_POR_ID);

			//Seta a preparedStatement
			preparedStatement.setInt(1, id);

			// Com o objeto já definido, joga ele para o ResultSet
			ResultSet rs = preparedStatement.executeQuery();

			Produto produto = null;
             
			// Seta um produto com dados do respectivo objeto 
			if (rs.next()) {
				produto = new Produto();
				produto.setId(rs.getInt("id"));
				produto.setUnidade(rs.getString("unidade"));
				produto.setDescricao(rs.getString("descricao"));
				produto.setDataCadastro(rs.getDate("data_cadastro"));
				produto.setEstoque(rs.getInt("estoque"));
			}

			return produto;

		} catch (SQLException e) {
			// caso ocorra qualquer erro ao executar a operacao no banco de dados
			throw new ErroDeBancoDeDados(e);

		} finally {

			// independente de sucesso/erro fecha a conexao com banco de dados
			fecharConexao();
		}

	}	
	
}
